from tortoise import fields
from tortoise.models import Model

from apps.models.fields import UnsignedBigIntField


class BaseModel(Model):
    id = UnsignedBigIntField(pk=True, description='主键')
    createDTTM = fields.DatetimeField(auto_now_add=True, null=False, description='创建时间')
    updateDTTM = fields.DatetimeField(auto_now=True, null=False, description='更新时间')
    isDelete = fields.BooleanField(null=False, default=False, description='删除标识')

    @property
    def createdAt(self) -> str:
        value = getattr(self, 'createDTTM')
        return value.strftime('%Y-%m-%d %H:%M:%S') if value else ''

    @property
    def updatedAt(self) -> str:
        value = getattr(self, 'updateDTTM')
        return value.strftime('%Y-%m-%d %H:%M:%S') if value else ''

    @property
    def startTimestamp(self) -> float:
        value = getattr(self, 'startTime', None) or getattr(self, 'startDate', None)
        return value.timestamp() if value else 0

    @property
    def endTimestamp(self) -> float:
        value = getattr(self, 'endTime', None) or getattr(self, 'endDate', None)
        return value.timestamp() if value else 0

    @property
    def startAt(self) -> str:
        value = getattr(self, 'startTime', None) or getattr(self, 'startDate', None)
        return value.strftime('%Y-%m-%d %H:%M:%S') if value else ''

    @startAt.setter
    def startAt(self, v):
        self.startAt = v

    @property
    def endAt(self) -> str:
        value = getattr(self, 'endTime', None) or getattr(self, 'endDate', None)
        return value.strftime('%Y-%m-%d %H:%M:%S')

    @endAt.setter
    def endAt(self, v):
        self.endAt = v

    class Meta:
        abstract = True


class ModelMixin(object):
    __slots__ = ()

    def __init__(self, **kwargs):
        pass

    @staticmethod
    def to_dict(instance, selects: tuple = None, excludes: tuple = None) -> dict:

        if not hasattr(instance, '_meta'):
            raise AssertionError('<%r> does not have attribute for _meta' % instance)

        if selects:
            return {i: getattr(instance, i) for i in selects}
        elif excludes:
            return {i: getattr(instance, i) for i in instance._meta.fields if i not in excludes}
        else:
            return {i: getattr(instance, i) for i in instance._meta.fields}

    async def async_to_dict(self, selects: tuple = None, excludes: tuple = None, second_attrs: dict = None) -> dict:
        """response dict data of instance serialize

        selects: ('id', 'name')
        excludes: ('created_at', 'updated_at')
        second_attrs: {'owner': ['id', 'name'], 'agency': ['id', 'name']}
        """

        results = self.to_dict(self, selects=selects, excludes=excludes)
        if second_attrs:
            for attr, columns in second_attrs.items():
                results.update({attr: self.to_dict(await getattr(self, attr), selects=columns)})

        return results

    def sync_to_dict(self, selects: tuple = None, excludes: tuple = None, second_attrs: dict = None) -> dict:
        """response dict data of instance serialize

        selects: ('id', 'name')
        excludes: ('created_at', 'updated_at')
        second_attrs: {'owner': ['id', 'name'], 'agency': ['id', 'name']}
        """

        results = self.to_dict(self, selects=selects, excludes=excludes)
        if second_attrs:
            for attr, columns in second_attrs.items():
                results.update({attr: self.to_dict(getattr(self, attr), selects=columns)})

        return results
